package com.itheima.pinda.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.pinda.entity.Rule;
import com.itheima.pinda.mapper.RuleMapper;
import com.itheima.pinda.service.ReloadDroolsService;
import lombok.extern.slf4j.Slf4j;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.Message;
import org.kie.api.runtime.KieContainer;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 重新加载数据库中的规则, 创建Drools相关对象
 *
 * @author llhuang10
 * @date 2021/10/12 15:29
 */
@Slf4j
@Service
public class ReloadDroolsServiceImpl extends ServiceImpl<RuleMapper, Rule> implements ReloadDroolsService {

    /**
     * 全局唯一容器对象, 用于创建Session操作Drools   是否存在线程安全问题?
     */
    public static KieContainer kieContainer;

    /**
     * 根据规则内容创建KieContainer对象
     *
     * @param ruleList 规则集合
     * @return KieContainer
     */
    @Override
    public KieContainer loadContainerFromString(List<Rule> ruleList) {
        long startTime = System.currentTimeMillis();
        KieServices kieServices = KieServices.Factory.get();
        // KieRepository 是一个单例, 充当所有可用 KieModules 的存储库
        KieRepository kieRepository = kieServices.getRepository();
        // 文件系统
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();

        ruleList.forEach(rule -> {
            String drl = rule.getContent();
            kieFileSystem.write("src/main/resources/" + drl.hashCode() + ".drl", drl);
        });

        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        if (kieBuilder.getResults().hasMessages(Message.Level.ERROR)) {
            throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().toString());
        }
        long endTime = System.currentTimeMillis();
        log.info("Time to build rules : {} ms", (endTime - startTime));
        startTime = System.currentTimeMillis();
        KieContainer kieContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
        endTime = System.currentTimeMillis();
        log.info("Time to load container : {} ms", (endTime - startTime));
        return kieContainer;
    }

    /**
     * 查询数据库中所有的规则
     *
     * @return list<Rule>
     */
    @Override
    public List<Rule> loadRules() {
        return super.list();
    }

    /**
     * 重新创建KieContainer对象
     */
    @Override
    public void reload() {
        KieContainer container = this.loadContainerFromString(this.loadRules());
        kieContainer = container;
    }
}
